#!/bin/sh
# ----------------------------------------------------------------------
#    Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
#     NOVELL (All rights reserved)
#    Copyright (c) 2008, 2009 Canonical, Ltd.
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of version 2 of the GNU General Public
#    License published by the Free Software Foundation.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# Authors:
#  Steve Beattie <steve.beattie@canonical.com>
#  Kees Cook <kees@ubuntu.com>
#
# /etc/init.d/apparmor
#
### BEGIN INIT INFO
# Provides: apparmor
# Required-Start: mountall
# Required-Stop: umountfs
# Default-Start: S
# Default-Stop:
# Short-Description: AppArmor initialization
# Description: AppArmor init script. This script loads all AppArmor profiles.
### END INIT INFO

. /etc/apparmor/functions
. /lib/lsb/init-functions

usage() {
    echo "Usage: $0 {start|stop|restart|reload|force-reload|status|recache}"
}

test -x ${PARSER} || exit 0 # by debian policy
# LSM is built-in, so it is either there or not enabled for this boot
test -d /sys/module/apparmor || exit 0

securityfs() {
	# Need securityfs for any mode
	if [ ! -d "${AA_SFS}" ]; then
		if cut -d" " -f2,3 /proc/mounts | grep -q "^${SECURITYFS} securityfs"'$' ; then
			log_action_msg "AppArmor not available as kernel LSM."
			log_end_msg 1
			exit 1
		else
			log_action_begin_msg "Mounting securityfs on ${SECURITYFS}"
			if ! mount -t securityfs none "${SECURITYFS}"; then
				log_action_end_msg 1
				log_end_msg 1
				exit 1
			fi
		fi
	fi
	if [ ! -w "$AA_SFS"/.load ]; then
		log_action_msg "Insufficient privileges to change profiles."
		log_end_msg 1
		exit 1
	fi
}

# Allow "recache" even when running on the liveCD
if [ "$1" = "recache" ]; then
	log_daemon_msg "Recaching AppArmor profiles"
	recache_profiles
	rc=$?
	log_end_msg "$rc"
	exit $rc
fi

# do not perform start/stop/reload actions when running from liveCD
test -d /rofs/etc/apparmor.d && exit 0

rc=255
case "$1" in
	start)
		log_daemon_msg "Starting AppArmor profiles"
		securityfs
		load_configured_profiles
		rc=$?
		log_end_msg "$rc"
		;;
	stop)
		log_daemon_msg "Clearing AppArmor profiles cache"
		clear_cache
		rc=$?
		log_end_msg "$rc"
		cat >&2 <<EOM
All profile caches have been cleared, but no profiles have been unloaded.
Unloading profiles will leave already running processes permanently
unconfined, which can lead to unexpected situations.

To set a process to complain mode, use the command line tool
'aa-complain'. To really tear down all profiles, run the init script
with the 'teardown' option."
EOM
		;;
	teardown)
		log_daemon_msg "Unloading AppArmor profiles"
		securityfs
		running_profile_names | while read profile; do
			if ! unload_profile "$profile" ; then
				log_end_msg 1
				exit 1
			fi
		done
		rc=0
		log_end_msg $rc
		;;
	restart|reload|force-reload)
		log_daemon_msg "Reloading AppArmor profiles"
		securityfs
		clear_cache
		load_configured_profiles
		rc=$?

		# Now, we have to find profiles that were removed.  Currently
		# we must re-parse all the profiles to get policy names.  :(
		aa_configured=$(mktemp -t aa-XXXXXX)
		configured_profile_names > "$aa_configured" || exit 1
		aa_loaded=$(mktemp -t aa-XXXXXX)
		running_profile_names > "$aa_loaded" || exit 1
		comm -2 -3 "$aa_loaded" "$aa_configured" | while read profile ; do
			unload_profile "$profile"
	        done
		rm -f "$aa_configured" "$aa_loaded"

		log_end_msg "$rc"
		;;
	status)
		securityfs
		if [ -x /usr/sbin/aa-status ]; then
			/usr/sbin/aa-status --verbose
		else
			cat "$AA_SFS"/profiles
		fi
		rc=$?
		;;
	*)
		usage
		rc=1
		;;
	esac
exit $rc
